﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace XYS.Service.Core.Util.Conventions;

/// <summary>
/// 
/// </summary>
public class ApplicationModelConvention : IApplicationModelConvention
{
    /// <summary>
    /// 
    /// </summary>
    public void Apply(ApplicationModel application)
    {
        //DELETE 自动支持多 Method
        HttpDeleteToMultiMethodConvention(application);
    }

    /// <summary>
    /// DELETE 自动支持多 Method
    /// </summary>
    /// <param name="application"></param>
    private void HttpDeleteToMultiMethodConvention(ApplicationModel application)
    {
        //遍历 控制器
        foreach (var controller in application.Controllers)
        {
            //遍历 Action
            foreach (var action in controller.Actions)
            {
                try
                {
                    //获取 HttpMethods
                    var httpMethods = action.Selectors
                        .Where(x => x.ActionConstraints.OfType<HttpMethodActionConstraint>().FirstOrDefault() != null)
                        .Select(x => x.ActionConstraints.OfType<HttpMethodActionConstraint>().First().HttpMethods.First())
                        .ToList();

                    //是否包含DELETE
                    if (httpMethods.Contains("DELETE"))
                    {
                        List<string> adds = new();

                        //获取内容
                        if (!httpMethods.Contains("GET")) adds.Add("GET");
                        if (!httpMethods.Contains("POST")) adds.Add("POST");

                        if (adds.Count == 0) continue;

                        //获取HttpDelete
                        var selector = action.Selectors
                        .Where(x => x.ActionConstraints.OfType<HttpMethodActionConstraint>().FirstOrDefault() != null
                        && x.ActionConstraints.OfType<HttpMethodActionConstraint>().FirstOrDefault().HttpMethods.Contains("DELETE"))
                        .FirstOrDefault();
                        var template = selector.AttributeRouteModel?.Template;

                        foreach (var item in adds)
                        {
                            var getSelector = new SelectorModel()
                            {
                                ActionConstraints = { new HttpMethodActionConstraint(new[] { item }) },
                                AttributeRouteModel = new AttributeRouteModel(new HttpGetAttribute(template))
                            };
                            action.Selectors.Add(getSelector);
                        }
                    }
                }
                catch { }
            }
        }
    }
}
